1 /*
2 * Copyright (C) 2008 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.google.common.primitives;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkElementIndex;
21 import static com.google.common.base.Preconditions.checkNotNull;
22 import static com.google.common.base.Preconditions.checkPositionIndexes;
23 import static java.lang.Float.NEGATIVE_INFINITY;
24 import static java.lang.Float.POSITIVE_INFINITY;
25
26 import com.google.common.annotations.Beta;
27 import com.google.common.annotations.GwtCompatible;
28 import com.google.common.base.Converter;
29
30 import java.io.Serializable;
31 import java.util.AbstractList;
32 import java.util.Collection;
33 import java.util.Collections;
34 import java.util.Comparator;
35 import java.util.List;
36 import java.util.RandomAccess;
37
38 /**
39 * Static utility methods pertaining to {@code float} primitives, that are not
40 * already found in either {@link Float} or {@link Arrays}.
41 *
42 * <p>See the Guava User Guide article on <a href=
43 * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
44 * primitive utilities</a>.
45 *
46 * @author Kevin Bourrillion
47 * @since 1.0
48 */
49 @GwtCompatible(emulated = true)
50 public final class Floats {
51 private Floats() {}
52
53 /**
54 * The number of bytes required to represent a primitive {@code float}
55 * value.
56 *
57 * @since 10.0
58 */
59 public static final int BYTES = Float.SIZE / Byte.SIZE;
60
61 /**
62 * Returns a hash code for {@code value}; equal to the result of invoking
63 * {@code ((Float) value).hashCode()}.
64 *
65 * @param value a primitive {@code float} value
66 * @return a hash code for the value
67 */
68 public static int hashCode(float value) {
69 // TODO(kevinb): is there a better way, that's still gwt-safe?
70 return ((Float) value).hashCode();
71 }
72
73 /**
74 * Compares the two specified {@code float} values using {@link
75 * Float#compare(float, float)}. You may prefer to invoke that method
76 * directly; this method exists only for consistency with the other utilities
77 * in this package.
78 *
79 * <p><b>Note:</b> this method simply delegates to the JDK method {@link
80 * Float#compare}. It is provided for consistency with the other primitive
81 * types, whose compare methods were not added to the JDK until JDK 7.
82 *
83 * @param a the first {@code float} to compare
84 * @param b the second {@code float} to compare
85 * @return the result of invoking {@link Float#compare(float, float)}
86 */
87 public static int compare(float a, float b) {
88 return Float.compare(a, b);
89 }
90
91 /**
92 * Returns {@code true} if {@code value} represents a real number. This is
93 * equivalent to, but not necessarily implemented as,
94 * {@code !(Float.isInfinite(value) || Float.isNaN(value))}.
95 *
96 * @since 10.0
97 */
98 public static boolean isFinite(float value) {
99 return NEGATIVE_INFINITY < value & value < POSITIVE_INFINITY;
100 }
101
102 /**
103 * Returns {@code true} if {@code target} is present as an element anywhere in
104 * {@code array}. Note that this always returns {@code false} when {@code
105 * target} is {@code NaN}.
106 *
107 * @param array an array of {@code float} values, possibly empty
108 * @param target a primitive {@code float} value
109 * @return {@code true} if {@code array[i] == target} for some value of {@code
110 * i}
111 */
112 public static boolean contains(float[] array, float target) {
113 for (float value : array) {
114 if (value == target) {
115 return true;
116 }
117 }
118 return false;
119 }
120
121 /**
122 * Returns the index of the first appearance of the value {@code target} in
123 * {@code array}. Note that this always returns {@code -1} when {@code target}
124 * is {@code NaN}.
125 *
126 * @param array an array of {@code float} values, possibly empty
127 * @param target a primitive {@code float} value
128 * @return the least index {@code i} for which {@code array[i] == target}, or
129 * {@code -1} if no such index exists.
130 */
131 public static int indexOf(float[] array, float target) {
132 return indexOf(array, target, 0, array.length);
133 }
134
135 // TODO(kevinb): consider making this public
136 private static int indexOf(
137 float[] array, float target, int start, int end) {
138 for (int i = start; i < end; i++) {
139 if (array[i] == target) {
140 return i;
141 }
142 }
143 return -1;
144 }
145
146 /**
147 * Returns the start position of the first occurrence of the specified {@code
148 * target} within {@code array}, or {@code -1} if there is no such occurrence.
149 *
150 * <p>More formally, returns the lowest index {@code i} such that {@code
151 * java.util.Arrays.copyOfRange(array, i, i + target.length)} contains exactly
152 * the same elements as {@code target}.
153 *
154 * <p>Note that this always returns {@code -1} when {@code target} contains
155 * {@code NaN}.
156 *
157 * @param array the array to search for the sequence {@code target}
158 * @param target the array to search for as a sub-sequence of {@code array}
159 */
160 public static int indexOf(float[] array, float[] target) {
161 checkNotNull(array, "array");
162 checkNotNull(target, "target");
163 if (target.length == 0) {
164 return 0;
165 }
166
167 outer:
168 for (int i = 0; i < array.length - target.length + 1; i++) {
169 for (int j = 0; j < target.length; j++) {
170 if (array[i + j] != target[j]) {
171 continue outer;
172 }
173 }
174 return i;
175 }
176 return -1;
177 }
178
179 /**
180 * Returns the index of the last appearance of the value {@code target} in
181 * {@code array}. Note that this always returns {@code -1} when {@code target}
182 * is {@code NaN}.
183 *
184 * @param array an array of {@code float} values, possibly empty
185 * @param target a primitive {@code float} value
186 * @return the greatest index {@code i} for which {@code array[i] == target},
187 * or {@code -1} if no such index exists.
188 */
189 public static int lastIndexOf(float[] array, float target) {
190 return lastIndexOf(array, target, 0, array.length);
191 }
192
193 // TODO(kevinb): consider making this public
194 private static int lastIndexOf(
195 float[] array, float target, int start, int end) {
196 for (int i = end - 1; i >= start; i--) {
197 if (array[i] == target) {
198 return i;
199 }
200 }
201 return -1;
202 }
203
204 /**
205 * Returns the least value present in {@code array}, using the same rules of
206 * comparison as {@link Math#min(float, float)}.
207 *
208 * @param array a <i>nonempty</i> array of {@code float} values
209 * @return the value present in {@code array} that is less than or equal to
210 * every other value in the array
211 * @throws IllegalArgumentException if {@code array} is empty
212 */
213 public static float min(float... array) {
214 checkArgument(array.length > 0);
215 float min = array[0];
216 for (int i = 1; i < array.length; i++) {
217 min = Math.min(min, array[i]);
218 }
219 return min;
220 }
221
222 /**
223 * Returns the greatest value present in {@code array}, using the same rules
224 * of comparison as {@link Math#min(float, float)}.
225 *
226 * @param array a <i>nonempty</i> array of {@code float} values
227 * @return the value present in {@code array} that is greater than or equal to
228 * every other value in the array
229 * @throws IllegalArgumentException if {@code array} is empty
230 */
231 public static float max(float... array) {
232 checkArgument(array.length > 0);
233 float max = array[0];
234 for (int i = 1; i < array.length; i++) {
235 max = Math.max(max, array[i]);
236 }
237 return max;
238 }
239
240 /**
241 * Returns the values from each provided array combined into a single array.
242 * For example, {@code concat(new float[] {a, b}, new float[] {}, new
243 * float[] {c}} returns the array {@code {a, b, c}}.
244 *
245 * @param arrays zero or more {@code float} arrays
246 * @return a single array containing all the values from the source arrays, in
247 * order
248 */
249 public static float[] concat(float[]... arrays) {
250 int length = 0;
251 for (float[] array : arrays) {
252 length += array.length;
253 }
254 float[] result = new float[length];
255 int pos = 0;
256 for (float[] array : arrays) {
257 System.arraycopy(array, 0, result, pos, array.length);
258 pos += array.length;
259 }
260 return result;
261 }
262
263 private static final class FloatConverter
264 extends Converter<String, Float> implements Serializable {
265 static final FloatConverter INSTANCE = new FloatConverter();
266
267 @Override
268 protected Float doForward(String value) {
269 return Float.valueOf(value);
270 }
271
272 @Override
273 protected String doBackward(Float value) {
274 return value.toString();
275 }
276
277 @Override
278 public String toString() {
279 return "Floats.stringConverter()";
280 }
281
282 private Object readResolve() {
283 return INSTANCE;
284 }
285 private static final long serialVersionUID = 1;
286 }
287
288 /**
289 * Returns a serializable converter object that converts between strings and
290 * floats using {@link Float#valueOf} and {@link Float#toString()}.
291 *
292 * @since 16.0
293 */
294 @Beta
295 public static Converter<String, Float> stringConverter() {
296 return FloatConverter.INSTANCE;
297 }
298
299 /**
300 * Returns an array containing the same values as {@code array}, but
301 * guaranteed to be of a specified minimum length. If {@code array} already
302 * has a length of at least {@code minLength}, it is returned directly.
303 * Otherwise, a new array of size {@code minLength + padding} is returned,
304 * containing the values of {@code array}, and zeroes in the remaining places.
305 *
306 * @param array the source array
307 * @param minLength the minimum length the returned array must guarantee
308 * @param padding an extra amount to "grow" the array by if growth is
309 * necessary
310 * @throws IllegalArgumentException if {@code minLength} or {@code padding} is
311 * negative
312 * @return an array containing the values of {@code array}, with guaranteed
313 * minimum length {@code minLength}
314 */
315 public static float[] ensureCapacity(
316 float[] array, int minLength, int padding) {
317 checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
318 checkArgument(padding >= 0, "Invalid padding: %s", padding);
319 return (array.length < minLength)
320 ? copyOf(array, minLength + padding)
321 : array;
322 }
323
324 // Arrays.copyOf() requires Java 6
325 private static float[] copyOf(float[] original, int length) {
326 float[] copy = new float[length];
327 System.arraycopy(original, 0, copy, 0, Math.min(original.length, length));
328 return copy;
329 }
330
331 /**
332 * Returns a string containing the supplied {@code float} values, converted
333 * to strings as specified by {@link Float#toString(float)}, and separated by
334 * {@code separator}. For example, {@code join("-", 1.0f, 2.0f, 3.0f)}
335 * returns the string {@code "1.0-2.0-3.0"}.
336 *
337 * <p>Note that {@link Float#toString(float)} formats {@code float}
338 * differently in GWT. In the previous example, it returns the string {@code
339 * "1-2-3"}.
340 *
341 * @param separator the text that should appear between consecutive values in
342 * the resulting string (but not at the start or end)
343 * @param array an array of {@code float} values, possibly empty
344 */
345 public static String join(String separator, float... array) {
346 checkNotNull(separator);
347 if (array.length == 0) {
348 return "";
349 }
350
351 // For pre-sizing a builder, just get the right order of magnitude
352 StringBuilder builder = new StringBuilder(array.length * 12);
353 builder.append(array[0]);
354 for (int i = 1; i < array.length; i++) {
355 builder.append(separator).append(array[i]);
356 }
357 return builder.toString();
358 }
359
360 /**
361 * Returns a comparator that compares two {@code float} arrays
362 * lexicographically. That is, it compares, using {@link
363 * #compare(float, float)}), the first pair of values that follow any
364 * common prefix, or when one array is a prefix of the other, treats the
365 * shorter array as the lesser. For example, {@code [] < [1.0f] < [1.0f, 2.0f]
366 * < [2.0f]}.
367 *
368 * <p>The returned comparator is inconsistent with {@link
369 * Object#equals(Object)} (since arrays support only identity equality), but
370 * it is consistent with {@link Arrays#equals(float[], float[])}.
371 *
372 * @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">
373 * Lexicographical order article at Wikipedia</a>
374 * @since 2.0
375 */
376 public static Comparator<float[]> lexicographicalComparator() {
377 return LexicographicalComparator.INSTANCE;
378 }
379
380 private enum LexicographicalComparator implements Comparator<float[]> {
381 INSTANCE;
382
383 @Override
384 public int compare(float[] left, float[] right) {
385 int minLength = Math.min(left.length, right.length);
386 for (int i = 0; i < minLength; i++) {
387 int result = Float.compare(left[i], right[i]);
388 if (result != 0) {
389 return result;
390 }
391 }
392 return left.length - right.length;
393 }
394 }
395
396 /**
397 * Returns an array containing each value of {@code collection}, converted to
398 * a {@code float} value in the manner of {@link Number#floatValue}.
399 *
400 * <p>Elements are copied from the argument collection as if by {@code
401 * collection.toArray()}. Calling this method is as thread-safe as calling
402 * that method.
403 *
404 * @param collection a collection of {@code Number} instances
405 * @return an array containing the same values as {@code collection}, in the
406 * same order, converted to primitives
407 * @throws NullPointerException if {@code collection} or any of its elements
408 * is null
409 * @since 1.0 (parameter was {@code Collection<Float>} before 12.0)
410 */
411 public static float[] toArray(Collection<? extends Number> collection) {
412 if (collection instanceof FloatArrayAsList) {
413 return ((FloatArrayAsList) collection).toFloatArray();
414 }
415
416 Object[] boxedArray = collection.toArray();
417 int len = boxedArray.length;
418 float[] array = new float[len];
419 for (int i = 0; i < len; i++) {
420 // checkNotNull for GWT (do not optimize)
421 array[i] = ((Number) checkNotNull(boxedArray[i])).floatValue();
422 }
423 return array;
424 }
425
426 /**
427 * Returns a fixed-size list backed by the specified array, similar to {@link
428 * Arrays#asList(Object[])}. The list supports {@link List#set(int, Object)},
429 * but any attempt to set a value to {@code null} will result in a {@link
430 * NullPointerException}.
431 *
432 * <p>The returned list maintains the values, but not the identities, of
433 * {@code Float} objects written to or read from it. For example, whether
434 * {@code list.get(0) == list.get(0)} is true for the returned list is
435 * unspecified.
436 *
437 * <p>The returned list may have unexpected behavior if it contains {@code
438 * NaN}, or if {@code NaN} is used as a parameter to any of its methods.
439 *
440 * @param backingArray the array to back the list
441 * @return a list view of the array
442 */
443 public static List<Float> asList(float... backingArray) {
444 if (backingArray.length == 0) {
445 return Collections.emptyList();
446 }
447 return new FloatArrayAsList(backingArray);
448 }
449
450 @GwtCompatible
451 private static class FloatArrayAsList extends AbstractList<Float>
452 implements RandomAccess, Serializable {
453 final float[] array;
454 final int start;
455 final int end;
456
457 FloatArrayAsList(float[] array) {
458 this(array, 0, array.length);
459 }
460
461 FloatArrayAsList(float[] array, int start, int end) {
462 this.array = array;
463 this.start = start;
464 this.end = end;
465 }
466
467 @Override public int size() {
468 return end - start;
469 }
470
471 @Override public boolean isEmpty() {
472 return false;
473 }
474
475 @Override public Float get(int index) {
476 checkElementIndex(index, size());
477 return array[start + index];
478 }
479
480 @Override public boolean contains(Object target) {
481 // Overridden to prevent a ton of boxing
482 return (target instanceof Float)
483 && Floats.indexOf(array, (Float) target, start, end) != -1;
484 }
485
486 @Override public int indexOf(Object target) {
487 // Overridden to prevent a ton of boxing
488 if (target instanceof Float) {
489 int i = Floats.indexOf(array, (Float) target, start, end);
490 if (i >= 0) {
491 return i - start;
492 }
493 }
494 return -1;
495 }
496
497 @Override public int lastIndexOf(Object target) {
498 // Overridden to prevent a ton of boxing
499 if (target instanceof Float) {
500 int i = Floats.lastIndexOf(array, (Float) target, start, end);
501 if (i >= 0) {
502 return i - start;
503 }
504 }
505 return -1;
506 }
507
508 @Override public Float set(int index, Float element) {
509 checkElementIndex(index, size());
510 float oldValue = array[start + index];
511 // checkNotNull for GWT (do not optimize)
512 array[start + index] = checkNotNull(element);
513 return oldValue;
514 }
515
516 @Override public List<Float> subList(int fromIndex, int toIndex) {
517 int size = size();
518 checkPositionIndexes(fromIndex, toIndex, size);
519 if (fromIndex == toIndex) {
520 return Collections.emptyList();
521 }
522 return new FloatArrayAsList(array, start + fromIndex, start + toIndex);
523 }
524
525 @Override public boolean equals(Object object) {
526 if (object == this) {
527 return true;
528 }
529 if (object instanceof FloatArrayAsList) {
530 FloatArrayAsList that = (FloatArrayAsList) object;
531 int size = size();
532 if (that.size() != size) {
533 return false;
534 }
535 for (int i = 0; i < size; i++) {
536 if (array[start + i] != that.array[that.start + i]) {
537 return false;
538 }
539 }
540 return true;
541 }
542 return super.equals(object);
543 }
544
545 @Override public int hashCode() {
546 int result = 1;
547 for (int i = start; i < end; i++) {
548 result = 31 * result + Floats.hashCode(array[i]);
549 }
550 return result;
551 }
552
553 @Override public String toString() {
554 StringBuilder builder = new StringBuilder(size() * 12);
555 builder.append('[').append(array[start]);
556 for (int i = start + 1; i < end; i++) {
557 builder.append(", ").append(array[i]);
558 }
559 return builder.append(']').toString();
560 }
561
562 float[] toFloatArray() {
563 // Arrays.copyOfRange() is not available under GWT
564 int size = size();
565 float[] result = new float[size];
566 System.arraycopy(array, start, result, 0, size);
567 return result;
568 }
569
570 private static final long serialVersionUID = 0;
571 }
572 }